﻿using Microsoft.AspNetCore.Http;

namespace Away.Common.Mvc.Logger;

/// <summary>
/// 收集接口请求日志
/// </summary>
public class RequestRawLoggerAttribute : ServiceFilterAttribute
{
    public RequestRawLoggerAttribute() : base(typeof(RequestRawLoggerFilter))
    {
    }
}


[ServiceInject(ServiceLifetime.Scoped, true)]
public class RequestRawLoggerFilter : IAsyncActionFilter
{
    private readonly ILogger<RequestRawLoggerFilter> _logger;
    public RequestRawLoggerFilter(ILogger<RequestRawLoggerFilter> logger)
    {
        _logger = logger;
    }
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        var request = context.HttpContext.Request;

        StringBuilder sb = new();
        sb.AppendLine($"{request.Method} {request.Path}{request.QueryString} {request.Protocol}");
        foreach (var (key, val) in request.Headers)
        {
            sb.AppendLine($"{key}: {val}");
        }
        sb.AppendLine();

        if (request.HasJsonContentType())
        {
            request.Body.Position = 0;
            var obj = await request.ReadFromJsonAsync<object>();
            var json = JsonSerializer.Serialize(obj);
            sb.AppendLine(json);
        }

        if (request.HasFormContentType)
        {
            if (request.ContentType!.Contains("multipart/form-data"))
            {
                var banner = $"--{request.ContentType?.Split(";")[1].Split("=")[1]}";
                foreach (var item in request.Form.Files)
                {
                    sb.AppendLine(banner);
                    sb.AppendLine($"Content-Disposition: {item.ContentDisposition}");
                    sb.AppendLine($"Content-Type: {item.ContentType}");
                    sb.AppendLine();
                    sb.AppendLine();
                    sb.AppendLine();
                }

                foreach (var (key, val) in request.Form)
                {
                    sb.AppendLine(banner);
                    sb.AppendLine($"Content-Disposition: form-data; name=\"{key}\"");
                    sb.AppendLine();
                    sb.AppendLine();
                    sb.AppendLine(val);
                }
                sb.AppendLine($"{banner}--");
            }
            else
            {
                sb.AppendLine(string.Join("&", request.Form.Select(o => $"{o.Key}={o.Value}")));
            }
        }

        sb.AppendLine();
        _logger.LogInformation("{}", sb.ToString());
        //Console.WriteLine(sb.ToString());
        await next();
    }
}
